/**
 * PUBLIC SECTION
 */
/**
 * IMPLEMENTATION
 */

jws.BristlePlugIn = {

  // namespace for shared objects plugin
  // if namespace is changed update server plug-in accordingly!
  NS: "bristlePlugin",

  NOT_CONNECTED : 0,
  CONNECTED : 1,
  LOGGED : 2,

  state : 0,

  developmentConsole : false,

  eventHandler : new EventHandler.BristleEventHandler(),
  actions : new BristleActions(),



  requestAction: function(actionName, params, callback) {
    var lRes = this.createDefaultResult();
    if (this.isConnected()) {
      //create new token
      var lToken = {
        ns: jws.BristlePlugIn.NS,
        type: actionName
      };

      //copy params to token
      Bristle.deepCopy(params, lToken);

      var options = {};

      //set action callback
      if (callback) {
        options.OnResponse = Bristle.addCallback(callback);
      }

      this.sendToken(lToken, options);
    } else {
      alert("NOT CONNECTED");
      lRes.code = -1;
      lRes.localeKey = "jws.jsc.res.notConnected";
      lRes.msg = "Not connected.";
    }
    return lRes;
  },

  /**
   * Starts connection to Bristleback server
   * @param config Configuration options are:
   * serverUrl - url of Bristleback server - default   JWS_SERVER_URL: "ws://" + ( self.location.hostname ? self.location.hostname : "localhost" ) + ":8787"
   * protocol - default json
   * timeout - default 360000
   * onOpenCallback function called after connection is established - default alert("connected")
   * onMessageCallback function called after message from server is received, change it only is special circumstances, overriding will cause plugin to malfunction
   * onCloseCallback function called after connection connection is closed - default alert("disconnected")
   */
  openConnection : function(config) {
    this.eventHandler.setConnector(this);
    this.actions.setConnector(this);

    if (typeof config === "undefined") {
      config = {};
    }
    var serverUrl = config.serverUrl || jws.JWS_SERVER_URL;
    var protocol = config.protocol || "json";
    var timeout = config.timeout || 360000;
    var useConsole = config.developmentConsole || false;
    if (useConsole) {
      jws.BristlePlugIn.developmentConsole = true;
      Bristle.appendConsole();
    }


    var onOpenCallback = config.OnOpen || function(aEvent) {
      alert("connected");
    };


    var handler = this.eventHandler;
    var onMessageCallback = config.OnMessage || function(aEvent, aToken) {
      handler.handleIncomingMessage(aEvent, aToken);
    };


    var onCloseCallback = config.OnClose || function(aEvent) {
      alert("disconnected");
    };

    var result = this.open(serverUrl + "/;prot=" + protocol + ",timeout=" + timeout, {
      OnOpen: onOpenCallback,
      OnMessage: onMessageCallback,
      OnClose: onCloseCallback
    });

    if (result.code != -1) {
      this.state = this.CONNECTED;
    } else {
      throw new Error(result.msg);
    }

     Bristle.compatibility.getCompatibilityInfo();
  },

  /**
   * Request action to login a user
   * If user is already logged in Error is thrown
   * If connection is not established Error is thrown
   * @param username
   * @param password
   * @param callback function called after log in user
   */
  loginUser : function(username, password, callback) {
    if (this.state == this.LOGGED) {
      throw Error("User already logged");
    }
    if (this.state == this.NOT_CONNECTED) {
      throw Error("Connection no established");
    }
    this.requestAction(Bristle.actionNames.LOG_IN_ACTION_NAME,
    {
      username : username,
      password : password
    },
      callback);
    //todo handle login error, do not state then
    this.state = this.LOGGED;
  },

  /**
   * Request action to log off a user
   * If user is not logged Error is thrown
   * If connection is not established Error is thrown
   * @param callback
   */
  logoutUser : function(callback) {
    if (this.state == this.CONNECTED) {
      throw Error("User not logged");
    }
    if (this.state == this.NOT_CONNECTED) {
      throw Error("Connection no established");
    }
    this.requestAction(Bristle.actionNames.LOG_OFF_ACTION_NAME, {}, callback);
    //todo handle login error, do not state then
    this.state = this.CONNECTED;
  },

  /**
   * Closes connection to bristleback server
   * If connection is not established, Error is thrown
   * @param config
   */
  closeConnection : function(config) {
    if (this.state == this.NOT_CONNECTED) {
      throw Error("Connection not established yet");
    }

    var result = this.close(config);
    if (result == -1) {
      throw Error("Can't close connection to bristleback server")
    }
    this.state = this.NOT_CONNECTED;
  }

};
jws.oop.addPlugIn(jws.jWebSocketTokenClient, jws.BristlePlugIn);

